home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / fslcl / fslclAttributes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  11.8 KB  |  347 lines

  1. /*
  2.  * fslclAttributes.c --
  3.  *
  4.  *    This has procedures for operations done on file attributes.
  5.  *    The general strategy when getting attributes is to make one call to
  6.  *    the name server to get an initial version of the attributes, and
  7.  *    then make another call to the I/O server to update things like
  8.  *    the access time and modify time.  There are two ways to get to
  9.  *    the name server, either via a pathname or an open file.  The
  10.  *    I/O server is always contacted using a fileID.
  11.  *
  12.  * Copyright 1987 Regents of the University of California
  13.  * All rights reserved.
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/fslcl/fslclAttributes.c,v 9.5 91/09/10 18:38:49 rab Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27.  
  28. #include <sprite.h>
  29. #include <fs.h>
  30. #include <fsutil.h>
  31. #include <fsconsist.h>
  32. #include <fsNameOps.h>
  33. #include <fslclInt.h>
  34. #include <fscache.h>
  35. #include <fsdm.h>
  36. #include <fsStat.h>
  37. #include <rpc.h>
  38.  
  39.  
  40. /*
  41.  *----------------------------------------------------------------------
  42.  *
  43.  * FslclGetAttr --
  44.  *
  45.  *    Get the attributes of a local file given its fileID.  This is called
  46.  *    from Fs_GetAttrStream to get the attributes from the file descriptor.
  47.  *    Also, as a special case, files that are cached remotely have their
  48.  *    attributes updated here (on the server) by doing a call-back to
  49.  *    clients to get the most recent access time, modify time, and size.
  50.  *
  51.  * Results:
  52.  *    An error code.
  53.  *
  54.  * Side effects:
  55.  *    Fills in the attributes structure with info from the disk descriptor.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59. ReturnStatus
  60. FslclGetAttr(fileIDPtr, clientID, attrPtr)
  61.     register Fs_FileID        *fileIDPtr;    /* Identfies file */
  62.     int                clientID;    /* Host ID of process asking
  63.                          * for the attributes */
  64.     register Fs_Attributes    *attrPtr;    /* Return - the attributes */
  65. {
  66.     if (fileIDPtr->type != FSIO_LCL_FILE_STREAM) {
  67.     panic( "FslclGetAttr, bad fileID type <%d>\n",
  68.         fileIDPtr->type);
  69.     return(GEN_INVALID_ARG);
  70.     } else {
  71.     Fsio_FileIOHandle *handlePtr;
  72.     Boolean isExeced;
  73.     ReturnStatus status;
  74.  
  75.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  76.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  77.         status = Fsio_LocalFileHandleInit(fileIDPtr, (char *)NIL,
  78.         (Fsdm_FileDescriptor *) NIL,  FALSE, &handlePtr);
  79.         if (status != SUCCESS) {
  80.         bzero((Address)attrPtr, sizeof(Fs_Attributes));
  81.         return(status);
  82.         }
  83.     }
  84.     /*
  85.      * Call-back to clients to get cached attributes, then copy
  86.      * attributes from the file descriptor to the attributes struct.
  87.      * NOTE: this only gets cached attributes for regular files.
  88.      * Device servers may cache attributes too, but that is handled
  89.      * on the client, not here on the name server.  Why?  Because
  90.      * generic devices crossed with migration lead to cases where
  91.      * we, the name server, don't know what's happening on the client.
  92.      */
  93.     Fsconsist_GetClientAttrs(handlePtr, clientID, &isExeced);
  94.     FslclAssignAttrs(handlePtr, isExeced, attrPtr);
  95.     Fsutil_HandleRelease(handlePtr, TRUE);
  96.     return(SUCCESS);
  97.     }
  98. }
  99.  
  100. /*
  101.  *----------------------------------------------------------------------
  102.  *
  103.  * FslclAssignAttrs --
  104.  *
  105.  *    Fill in the Fs_Attributes structure for a regular file.
  106.  *    If the isExeced flag is TRUE then the current time is used as the
  107.  *    access time.  This is an optimization to avoid contacting every
  108.  *    client using the file.  Furthermore, due to segment caching by
  109.  *    VM, we have no accurate access time on an executable anyway.
  110.  *
  111.  * Results:
  112.  *    None.
  113.  *
  114.  * Side effects:
  115.  *    Attribute structure set to contain attributes from disk descriptor
  116.  *    and the cache information.
  117.  *
  118.  *----------------------------------------------------------------------
  119.  */
  120. void
  121. FslclAssignAttrs(handlePtr, isExeced, attrPtr)
  122.     register    Fsio_FileIOHandle    *handlePtr;
  123.     Boolean                isExeced;  /* TRUE if being executed,
  124.                             * use current time for
  125.                             * the access time. */
  126.     register    Fs_Attributes        *attrPtr;
  127. {
  128.     register Fsdm_FileDescriptor *descPtr = handlePtr->descPtr;
  129.     register Fscache_FileInfo *cacheInfoPtr = &handlePtr->cacheInfo;
  130.  
  131.     attrPtr->serverID            = handlePtr->hdr.fileID.serverID;
  132.     attrPtr->domain            = handlePtr->hdr.fileID.major;
  133.     attrPtr->fileNumber            = handlePtr->hdr.fileID.minor;
  134.     attrPtr->type            = descPtr->fileType;
  135.     attrPtr->permissions        = descPtr->permissions;
  136.     attrPtr->numLinks            = descPtr->numLinks;
  137.     attrPtr->uid            = descPtr->uid;
  138.     attrPtr->gid            = descPtr->gid;
  139.     attrPtr->userType            = descPtr->userType;
  140.     attrPtr->devServerID        = descPtr->devServerID;
  141.     attrPtr->devType            = descPtr->devType;
  142.     attrPtr->devUnit            = descPtr->devUnit;
  143.     /*
  144.      * Take creation and descriptor modify time from disk descriptor,
  145.      * except that the descModifyTime is >= dataModifyTime.  This
  146.      * constraint is enforced later when the descriptor is written back,
  147.      * so the descriptor may still be out-of-date at this point.
  148.      */
  149.     attrPtr->createTime.seconds        = descPtr->createTime;
  150.     attrPtr->createTime.microseconds    = 0;
  151.     attrPtr->descModifyTime.seconds    = descPtr->descModifyTime;
  152.     attrPtr->descModifyTime.microseconds= 0;
  153.     if (cacheInfoPtr->attr.modifyTime > attrPtr->descModifyTime.seconds) {
  154.     attrPtr->descModifyTime.seconds = cacheInfoPtr->attr.modifyTime;
  155.     }
  156.     /*
  157.      * Take size, access time, and modify time from cache info because
  158.      * remote caching means the disk descriptor attributes can be out-of-date.
  159.      */
  160.     attrPtr->size            = cacheInfoPtr->attr.lastByte + 1;
  161.     if (cacheInfoPtr->attr.firstByte >= 0) {
  162.     attrPtr->size            -= cacheInfoPtr->attr.firstByte;
  163.     }
  164.     attrPtr->dataModifyTime.seconds    = cacheInfoPtr->attr.modifyTime;
  165.     attrPtr->dataModifyTime.microseconds= 0;
  166.     if (isExeced) {
  167.     attrPtr->accessTime.seconds    = Fsutil_TimeInSeconds();
  168.     } else {
  169.     attrPtr->accessTime.seconds    = cacheInfoPtr->attr.accessTime;
  170.     }
  171.     attrPtr->accessTime.microseconds    = 0;
  172.     /*
  173.      * Again, if delayed writes mean we don't have any blocks for the
  174.      * file then we estimate a block count from the cache size.  This
  175.      * can be wrong due to granularity errors and wholes in files.
  176.      * Also, even if the descriptor has some blocks it may not have them all.
  177.      */
  178.     if (cacheInfoPtr->attr.lastByte > 0 && descPtr->numKbytes == 0) {
  179.     attrPtr->blocks            = cacheInfoPtr->attr.lastByte / 1024 +1;
  180.     } else {
  181.     attrPtr->blocks            = descPtr->numKbytes;
  182.     }
  183.     attrPtr->blockSize            = FS_BLOCK_SIZE;
  184.     attrPtr->version            = descPtr->version;
  185.     attrPtr->userType            = descPtr->userType;
  186. }
  187.  
  188. /*
  189.  *----------------------------------------------------------------------
  190.  *
  191.  * FslclSetAttr --
  192.  *
  193.  *    Set the attributes of a local file given its fileID.  This is
  194.  *    called from Fs_SetAttrStream to set the attributes at the name server.
  195.  *    The flags argument defines which attributes are updated.
  196.  *    This updates the disk descriptor and copies the new information
  197.  *     into the cache.  It will go to disk on the next sync.
  198.  *
  199.  *    Various constraints are implemented here.
  200.  *    1) You must be super-user or own the file to succeed at all.
  201.  *    2) You must be super-user to change the owner of a file.
  202.  *    3) You must be super-user or a member of the new group
  203.  *        to change the group of a file.  The SETGID bit is
  204.  *        cleared if a non-super-user changes the group.
  205.  *    4) You must be super-user or a member of the file's group
  206.  *        to set the SETGID bit of the file.
  207.  *    5) If you've made it this far you can set the access time,
  208.  *        modify time, and user-defined file type.
  209.  *
  210.  * Results:
  211.  *    FS_NOT_OWNER if you don't own the file
  212.  *    FS_NO_ACCESS if you violate one of the above constraints.
  213.  *
  214.  * Side effects:
  215.  *    Sets the attributes of the file, subject to the above constraints.
  216.  *
  217.  *----------------------------------------------------------------------
  218.  */
  219. ReturnStatus
  220. FslclSetAttr(fileIDPtr, attrPtr, idPtr, flags)
  221.     Fs_FileID            *fileIDPtr;    /* Target file. */
  222.     register Fs_Attributes    *attrPtr;    /* New attributes */
  223.     register Fs_UserIDs        *idPtr;        /* Process's owner/group */
  224.     register int        flags;        /* What attrs to set */
  225. {
  226.     register ReturnStatus    status = SUCCESS;
  227.     Fsio_FileIOHandle        *handlePtr;
  228.     register Fsdm_FileDescriptor    *descPtr;
  229.  
  230.     handlePtr = Fsutil_HandleFetchType(Fsio_FileIOHandle, fileIDPtr);
  231.     if (handlePtr == (Fsio_FileIOHandle *)NIL) {
  232.     printf(
  233.         "FslclSetAttr, no handle for %s <%d,%d,%d>\n",
  234.         Fsutil_FileTypeToString(fileIDPtr->type),
  235.         fileIDPtr->serverID, fileIDPtr->major, fileIDPtr->minor);
  236.     return(FS_FILE_NOT_FOUND);
  237.     }
  238.     descPtr = handlePtr->descPtr;
  239.     if (descPtr == (Fsdm_FileDescriptor *)NIL) {
  240.     printf( "FslclSetAttr, NIL descPtr\n");
  241.     status = FAILURE;
  242.     goto exit;
  243.     }
  244.     if ((idPtr->user != 0) && (idPtr->user != descPtr->uid)) {
  245.     status = FS_NOT_OWNER;
  246.     goto exit;
  247.     }
  248.     if (flags & FS_SET_OWNER) {
  249.     if (attrPtr->uid >= 0 && descPtr->uid != attrPtr->uid) {
  250.         if (idPtr->user != 0) {
  251.         /*
  252.          * Don't let ordinary people give away ownership.
  253.          */
  254.         status = FS_NO_ACCESS;
  255.         goto exit;
  256.         } else {
  257.         descPtr->uid = attrPtr->uid;
  258.         descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  259.         }
  260.     }
  261.     if (attrPtr->gid >= 0 && descPtr->gid != attrPtr->gid) {
  262.         register int g;
  263.         /*
  264.          * Can only set to a group you belong to.  The set-gid
  265.          * bit is also reset as an extra precaution.
  266.          */
  267.         for (g=0 ; g < idPtr->numGroupIDs; g++) {
  268.         if (attrPtr->gid == idPtr->group[g] || idPtr->user == 0) {
  269.             descPtr->gid = attrPtr->gid;
  270.             descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  271.             if (idPtr->user != 0) {
  272.             descPtr->permissions &= ~FS_SET_GID;
  273.             descPtr->flags |= FSDM_FD_PERMISSIONS_DIRTY;
  274.             }
  275.             break;
  276.         }
  277.         }
  278.         if (g >= idPtr->numGroupIDs) {
  279.         status = FS_NO_ACCESS;
  280.         goto exit;
  281.         }
  282.     }
  283.     }
  284.     if (flags & FS_SET_MODE) {
  285.     if (attrPtr->permissions & FS_SET_GID) {
  286.         /*
  287.          * Have to verify that the process belongs to the
  288.          * new group of the file.  We have already verified that
  289.          * the process's user ID matches the file's owner.
  290.          */
  291.         register int g;
  292.         for (g=0 ; g < idPtr->numGroupIDs; g++) {
  293.         if (attrPtr->gid == idPtr->group[g] || idPtr->user == 0) {
  294. #ifndef lint
  295.             goto setMode;
  296. #endif not lint
  297.         }
  298.         }
  299.         status = FS_NO_ACCESS;
  300.         goto exit;        /* Note: can't have changed *descPtr by now. */
  301.     }
  302. #ifndef lint
  303. setMode:
  304. #endif not lint
  305.     descPtr->permissions = attrPtr->permissions;
  306.     descPtr->flags |= FSDM_FD_PERMISSIONS_DIRTY;
  307.     }
  308.     if (flags & FS_SET_DEVICE) {
  309.     if (descPtr->fileType == FS_DEVICE ||
  310.           descPtr->fileType == FS_REMOTE_DEVICE) {
  311.           descPtr->devServerID = attrPtr->devServerID;
  312.           descPtr->devType = attrPtr->devType;
  313.           descPtr->devUnit = attrPtr->devUnit;
  314.           descPtr->flags |= FSDM_FD_OTHERS_DIRTY;
  315.     }
  316.     }
  317.     if (flags & FS_SET_TIMES) {
  318.     descPtr->accessTime       = attrPtr->accessTime.seconds;
  319.     descPtr->dataModifyTime   = attrPtr->dataModifyTime.seconds;
  320.         descPtr->flags |= (FSDM_FD_ACCESSTIME_DIRTY|FSDM_FD_MODTIME_DIRTY);
  321.     /*
  322.      * Patch this because it gets copied below by Fscache_UpdateCachedAttr.
  323.      */
  324.     attrPtr->createTime.seconds = descPtr->createTime;
  325.     }
  326.  
  327.     if (flags & FS_SET_FILE_TYPE) {
  328.     descPtr->userType    = attrPtr->userType;
  329.         descPtr->flags |= FSDM_FD_USERTYPE_DIRTY;
  330.     }
  331.  
  332.     /*
  333.      * Copy this new information into the cache block containing the descriptor.
  334.      */
  335.     descPtr->descModifyTime   = Fsutil_TimeInSeconds();
  336.     status = Fsdm_FileDescStore(handlePtr, FALSE);
  337.     if (status == SUCCESS) {
  338.     /*
  339.      * Update the attributes cached in the file handle.
  340.      */
  341.     Fscache_UpdateCachedAttr(&handlePtr->cacheInfo, attrPtr, flags);
  342.     }
  343. exit:
  344.     Fsutil_HandleRelease(handlePtr, TRUE);
  345.     return(status);
  346. }
  347.